package goredis

import (
	"context"
	"reflect"
	"strconv"
	"time"

	"gitee.com/MikeDDD/gu/logs"
	"github.com/go-redis/redis/v8"
)

// 获取slice、map、ptr里结构体最终类型
func getStructType(p any) reflect.Type {
	reflectType := reflect.ValueOf(p).Type()
	for reflectType.Kind() == reflect.Slice || reflectType.Kind() == reflect.Map || reflectType.Kind() == reflect.Ptr {
		reflectType = reflectType.Elem()
	}
	return reflectType
}

var DefaultClient *RedisClienterInstance

type RedisClienterInstance struct {
	Rc       *redis.Client
	context  context.Context
	serverid string
}

func (r *RedisClienterInstance) ctx() context.Context {
	return r.context
}

func Init(addr, username, password string, db int32) {
	DefaultClient = New(addr, username, password, db)
}

func New(addr, username, password string, db int32) *RedisClienterInstance {
	logs.Info("start default redis client addr:%v, password:%v, db:%v", addr, password, db)

	return &RedisClienterInstance{
		Rc: redis.NewClient(&redis.Options{
			Addr:     addr,
			Username: username,
			Password: password,
			//DB:       int(db),
		}),
		context:  context.Background(),
		serverid: strconv.Itoa(int(db)),
	}
}

// EXPIRE 为key设置过期时间, key:键 timestamp:过期时间(秒)
func Expire(key any, t time.Duration) (err error) {
	return ExpireCli(DefaultClient, key, t)
}

func Persist(key any) (err error) {
	return PersistCli(DefaultClient, key)
}

func TTL(key any) (s time.Duration, err error) {
	return TTLCli(DefaultClient, key)
}

// KEYS, key:键  s:域切片
func Keys(key any) (field []string, err error) {
	return KeysCli(DefaultClient, key)
}

// DEL 删除键, keys：一个或多个键
func Del(keys ...string) error {
	return DelCli(DefaultClient, keys...)
}

// EXISTS 判断键是否存在, key：键
func Exists(key any) (bool, error) {
	return ExistsCli(DefaultClient, key)
}

// SET 扩展, rKey:键 p:protobuf结构引用
func SetExt(key any, p any) (err error) {
	return SetExtCli(DefaultClient, key, p)
}

func Set(key, value string) error {
	return SetCli(DefaultClient, key, value, -1)
}

func SetWithTTL(key, value string, ttl time.Duration) error {
	return SetCli(DefaultClient, key, value, ttl)
}

func SetCasWithTTL(key, oldValue, newValue string, second int64) (bool, error) {
	return SetCliCas(DefaultClient, key, oldValue, newValue, second)
}

func Eval(script string, key string, args []any) (any, bool, error) {
	return EvalCli(DefaultClient, script, key, args)
}

// GET 扩展, key:键 p:protobuf结构引用
func GetExt(key any, p any) (exists bool, err error) {
	return GetExtCli(DefaultClient, key, p)
}

func Get(key string) (value string, err error) {
	return GetCli(DefaultClient, key)
}

func HGet(key any, field any) string {
	return HGetCli(DefaultClient, key, field)
}

// HGET 扩展, key:键 field:域 p:protobuf结构引用
func HGetExt(key any, field any, p any) (exists bool, ok bool) {
	return HGetExtCli(DefaultClient, key, field, p)
}

func HSet(key any, field any, p any) bool {
	return HSetCli(DefaultClient, key, field, p)
}

// HSET 扩展, key:键 field:域 p:protobuf结构引用
func HSetExt(key any, field any, p any) (err error) {
	return HSetExtCli(DefaultClient, key, field, p)
}

func HVals(key any) (p []string, err error) {
	return HValsCli(DefaultClient, key)
}

// HGET 扩展, key:键  p:protobuf结构引用切片
func HValsExt(key any, p any) (err error) {
	return HValsExtCli(DefaultClient, key, p)
}

func HLen(key any) (int64, error) {
	return HLenCli(DefaultClient, key)
}

// HDEL 删除键, key：键, fields：一个或多个域
func HDel(key string, fields ...string) error {
	return HDelCli(DefaultClient, key, fields...)
}

// HEXISTS 判断键中域是否存在, key：键, field：域
func HExists(key any, field any) (bool, error) {
	return HExistsCli(DefaultClient, key, field)
}

// HKEYS, key:键  s:域切片
func HKeys(key any) (field []string, err error) {
	return HKeysCli(DefaultClient, key)
}

func HIncrBy(rk, hk string, hv int64) int64 {
	return HIncrByCli(DefaultClient, rk, hk, hv)
}

func ZAdd(key string, score float64, member string) (err error) {
	return ZAddCli(DefaultClient, key, score, member)
}

func ZIncrBy(key string, score float64, member string) (err error) {
	return ZIncrByCli(DefaultClient, key, score, member)
}

func ZRevRangeWithScores(key string, start, stop int64) (err error, memberResult []string, scoreResult []float64) {
	return ZRevRangeWithScoresCli(DefaultClient, key, start, stop)
}

func ZRevRangeByScoreWithScores(key string, min, max string, offset, count int64) (err error, memberResult []string, scoreResult []float64) {
	return ZRevRangeByScoreWithScoresCli(DefaultClient, key, min, max, offset, count)
}

func ZRangeByScoreWithScores(key string, min, max string, offset, count int64) (err error, memberResult []string, scoreResult []float64) {
	return ZRangeByScoreWithScoresCli(DefaultClient, key, min, max, offset, count)
}

func ZRangeByScore(key string, min, max string, offset, count int64) (err error, memberResult []string) {
	return ZRangeByScoreCli(DefaultClient, key, min, max, offset, count)
}

func ZRevRange(key string, start, stop int64) (err error, memberResult []string) {
	return ZRevRangeCli(DefaultClient, key, start, stop)
}

func ZRangeWithScores(key string, start, stop int64) (err error, memberResult []string, scoreResult []float64) {
	return ZRangeWithScoresCli(DefaultClient, key, start, stop)
}

// ZREM 移除有序集 key 中的一个或多个成员，不存在的成员将被忽略。, key：键, member: 一个或多个成员
func ZRem(key string, member ...string) error {
	return ZRemCli(DefaultClient, key, member...)
}

// ZREVRANK key:键, rank排名 第1名为0, 无排名为-1 (降序)
//
// 有数据 cmd.Err()==nil
//
// 无数据 cmd.Err()==redis.Nil
func ZRevRank(key string, member string) (rank int64, err error) {
	return ZRevRankCli(DefaultClient, key, member)
}

// ZSCORE key:键, 返回有序集 key 中，成员 member 的 score 值。
func ZScore(key string, member string) (score float64, err error) {
	return ZScoreCli(DefaultClient, key, member)
}

func ZCard(key string) (cnt int64, err error) {
	return ZCardCli(DefaultClient, key)
}

// ZRANK key:键, rank排名 第1名为0, 无排名为-1 (升序)
func ZRank(key string, member string) (rank int64, err error) {
	return ZRankCli(DefaultClient, key, member)
}

// LPUSH, key:键, p=protobuf结构引用
func LPushExt(key any, p any) (err error) {
	return LPushExtCli(DefaultClient, key, p)
}

func RPushExt(key any, p any) (err error) {
	return RPushExtCli(DefaultClient, key, p)
}

func RPush(key, value string) (err error) {
	return RPushCli(DefaultClient, key, value)
}

// LRANGE, key:键, slicePrt=protobuf结构引用切片, start, stop 范围(包含)
func LRangeExt(key any, slicePrt any, start, stop int64) (err error) {
	return LRangeExtCli(DefaultClient, key, slicePrt, start, stop)
}

// LLEN, key：键
func LLen(key any) (int64, error) {
	return LLenCli(DefaultClient, key)
}

// DoRPop
func RPop(key any) (value string, err error) {
	return RPopCli(DefaultClient, key)
}

func LPop(key any) (value string, err error) {
	return LPopCli(DefaultClient, key)
}
